#include "StdAfx.h"
#include "NetworkController.h"

///////////////////// PACKET STREAM //////////////////////////////

sf::Packet& operator <<(sf::Packet& Packet, const HPacket& h)
{
	return Packet << h.m_cmd_number << h.m_infos_cmd << h.m_time;
}

sf::Packet& operator >>(sf::Packet& Packet, HPacket& h)
{
	 return Packet >> h.m_cmd_number >> h.m_infos_cmd >> h.m_time;
}

///////////////////// LOOP //////////////////////////////////

static void networkLoop()
{
	Player cu = DataBase::getInstance()->getCurrentPlayer();

	while(NetworkController::getInstance()->getStatus())
	{
		sf::Packet packet;
		sf::Socket::Status st;
		HPacket hp;


		//RECIEVE LOGIC
		st = NetworkController::getInstance()->m_socket.receive(packet);
			
		switch(st)
		{
		case sf::Socket::Status::Done:
			if (packet)
			{
				packet >> hp;
			
				switch(hp.m_cmd_number)
				{
				case 0: NetworkController::getInstance()->startGame(hp.m_infos_cmd);
						break;
				case 1: NetworkController::getInstance()->refreshTime(hp.m_infos_cmd);
						break;
				case 2: NetworkController::getInstance()->endGame(hp.m_infos_cmd);
						break;
				case 4: NetworkController::getInstance()->refreshPlayers(hp.m_infos_cmd);
						break;
				case 5: NetworkController::getInstance()->deadPlayer(hp.m_infos_cmd);
						break;
				case 6: NetworkController::getInstance()->youAreDead(hp.m_infos_cmd);
						break;
				}
			}
			break;
		case sf::Socket::Status::Disconnected:
			NetworkController::getInstance()->setStatus(false);
			break;
		}

		if (cu.m_posX != DataBase::getInstance()->getCurrentPlayer().m_posX ||
			cu.m_posY != DataBase::getInstance()->getCurrentPlayer().m_posY)
		{
			//SEND LOGIC
			std::ostringstream oss1, oss2, oss3;
			Player cu = DataBase::getInstance()->getCurrentPlayer();

			oss1 << cu.m_posX;
			oss2 << cu.m_posY;
			oss3 << cu.m_number;

			hp.m_cmd_number = 3;
			hp.m_infos_cmd = sf::String(oss1.str() + "-" + oss2.str() + "-" + oss3.str());
			hp.m_time = sf::String("0");

			packet << hp;

			st = NetworkController::getInstance()->m_socket.send(packet);
			if (st != sf::Socket::Status::Done)
				NetworkController::getInstance()->setStatus(false);
			std::cout << "SEND PACKET" << std::endl;
		}
	}
}

NetworkController::NetworkController(void)
{
}

NetworkController::~NetworkController(void)
{
}

bool NetworkController::startService(std::string ip, int port)
{
	DataBase::getInstance()->initDatabase();
	if ((connectSocket(ip, port)) == false)
		return false;
	
	std::cout << "CONNECTED" << std::endl;
	m_networkLoop.create(networkLoop, NULL);
	return true;
}

void NetworkController::stopService()
{
	setStatus(false);
	m_networkLoop.join();
}

bool	NetworkController::connectSocket(std::string ip, int port)
{
	sf::Socket::Status st;
	setStatus(false);

	m_socket.setBlocking(false);
	st = m_socket.connect(ip, port); 

	if (st == sf::Socket::Status::Error)
		return false;

	setStatus(true);
	return true;
}


void	NetworkController::setStatus(bool s)
{
	m_mutexStatus.lock();
	m_status = s;
	m_mutexStatus.unlock();
}

bool	NetworkController::getStatus()
{
	m_mutexStatus.lock();
	bool s = m_status;
	m_mutexStatus.unlock();
	return s;
}

void NetworkController::startGame(std::string info)
{
	Player cu;
	
	cu.m_number = atoi(info.substr('/').c_str());
	cu.m_type = (TypePlayer)atoi(info.substr(info.find('/') + 1).c_str());

	DataBase::getInstance()->setState(GameState::START);
	DataBase::getInstance()->setState(GameState::INGAME);
}

void NetworkController::refreshTime(std::string info)
{
	//
}

void NetworkController::endGame(std::string info)
{
	DataBase::getInstance()->setState(GameState::STOP);
}

void NetworkController::refreshPlayers(std::string info)
{
	Player cu;
	
	std::string temp = info.substr('/').c_str();

	while (temp.size() > 0)
	{
		cu.m_posX = atoi(temp.substr('-').c_str());
		temp = temp.substr(temp.find('-') + 1);
		
		cu.m_posY = atoi(temp.substr('-').c_str());
		temp = temp.substr(temp.find('-') + 1);
		
		cu.m_number = atoi(temp.substr('-').c_str());

		DataBase::getInstance()->modifyPlayer(cu);

		std::string temp = temp.substr('/').c_str();
	}
}

void NetworkController::deadPlayer(std::string info)
{
	DataBase::getInstance()->erasePlayerNumber(atoi(info.c_str()));
}

void NetworkController::youAreDead(std::string info)
{
	std::cout << "YOU ARE DEAD" << std::endl;
}